package com.academy.image.finder.artesia;

import com.artesia.asset.Asset;
import com.artesia.asset.AssetIdentifier;
import com.artesia.asset.services.AssetDataLoadRequest;
import com.artesia.asset.services.AssetServices;
import com.artesia.common.exception.BaseTeamsException;
import com.artesia.entity.TeamsIdentifier;
import com.artesia.metadata.MetadataCollection;
import com.artesia.metadata.MetadataValue;
import com.artesia.security.SecuritySession;
import com.chesnutconsulting.otbasket.image.finder.ImageFinder;
import com.chesnutconsulting.otbasket.image.finder.artesia.OtBasketConfiguration;

import org.apache.commons.lang.StringUtils;
import com.google.common.base.Preconditions;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import javax.inject.Inject;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.InputStream;

/**
 * User: kandhari
 * Date: 2/18/13 8:27 PM
 * <p/>
 * Document me
 */
@Component
public class ArtesiaImageFinder implements ImageFinder {

	protected final OtBasketConfiguration otBasketConfiguration;
	private static final Logger LOGGER = LoggerFactory.getLogger(ArtesiaImageFinder.class);

	@Inject
	public ArtesiaImageFinder(
			OtBasketConfiguration academyBasketConfiguration) {
		this.otBasketConfiguration = academyBasketConfiguration;
        this.imageLoader = new ImageLoader();
	}

	public Map<String, String> getScalarMetadataForAsset(AssetIdentifier assetId) throws Exception {
		SecuritySession session = otBasketConfiguration.getSession();
		
		Map<String, String> assetMetadataMap = new HashMap<String, String>();
		AssetDataLoadRequest adlr = new AssetDataLoadRequest();
		adlr.setLoadAssetContentInfo(false);
		adlr.setLoadDestinationLinks(false);
		adlr.setLoadFPO(false);
		adlr.setLoadVocabularyTerms(false);
		adlr.setLoadMetadata(true);
		adlr.setLoadMetadataByModel(true);

		Asset asset = getAssetServices().retrieveAsset(assetId, adlr, session);
		if ( asset == null) 
		{
			LOGGER.info("Asset [{}] was not found for session [{}]", assetId.asString(), session.getLoginName());
			throw new BaseTeamsException ( "NONE.EXISTS", "Asset was not found" );
		}

		LOGGER.info("Current asset state {}", asset.getAssetState());
		MetadataCollection mdColl = asset.getMetadata();
		if (mdColl == null )
		{
			LOGGER.info("No metadata found for asset [{}] and session [{}]", assetId.asString(), session.getLoginName());
			return assetMetadataMap;
		}		

		List<TeamsIdentifier> fieldIdList = this.otBasketConfiguration.getScalarFieldList();
		for (TeamsIdentifier teamsIdentifier : fieldIdList) {
			MetadataValue mdValue = mdColl.getValueForField(teamsIdentifier);
			if ( mdValue == null || StringUtils.isEmpty(mdValue.getStringValue()))
			{
				assetMetadataMap.put(teamsIdentifier.asString(), "");
				System.out.println("Adding empty");
			}
			else
			{
				assetMetadataMap.put(teamsIdentifier.asString(), mdValue.getStringValue());				
				System.out.println("Adding " + mdValue.getStringValue());
			}
		}
		
		return assetMetadataMap;
	}

    protected AssetServices getAssetServices() {
        return AssetServices.getInstance();
    }

	public String getScreenResImageUrl( String imageId ) {
		return otBasketConfiguration.getBaseImageFetchUrl() + imageId;
	}

    protected final ImageLoader imageLoader;

    public File getImage(String imageId) {
        return imageLoader.getImage(imageId, otBasketConfiguration);
    }

    static class ImageLoader {
        public File getImage(String imageId, OtBasketConfiguration academyBasketConfiguration) {
            HttpClient client = null;
            try {
                client = login(academyBasketConfiguration.getArtesiaServerUrl(),
                                academyBasketConfiguration.getArtesiaUser(),
                                academyBasketConfiguration.getArtesiaPwd());
                String imageUrl = academyBasketConfiguration.getBaseImageFetchUrl() + imageId;
                HttpResponse imageResponse = getResponse(imageUrl, client);

                Preconditions.checkArgument("image/jpeg".equalsIgnoreCase(
                        imageResponse.getEntity().getContentType().getValue()));
                return saveImageToDisk(imageId, imageResponse);
            } finally {
                if (client != null) {
                    client.getConnectionManager().shutdown();
                }
            }
        }

        File saveImageToDisk(String imageId, HttpResponse response) {
            File preparedFile = prepareOutputFile(imageId);
            try {
                InputStream inputStream = response.getEntity().getContent();
                BufferedImage image = ImageIO.read(inputStream);
                preparedFile.createNewFile();
                ImageIO.write(image, "jpg", preparedFile);
                return preparedFile;
            } catch (Throwable e) {
                LOGGER.error("Error while reading input from stream", e);
                throw new AssertionError("Error while reading input from stream");
            }
        }

        File prepareOutputFile(String imageId) {
            try {
                File file = new File("/tmp/watermarked/" + imageId + ".jpg");
                if (!file.getParentFile().exists()) {
                    LOGGER.debug("Adding output directory=%s", file.getParentFile().getPath());
                    file.getParentFile().mkdirs();
                }

                return file;
            } catch (Throwable e) {
                LOGGER.error("Error while preparing output file", e);
                throw new AssertionError("Error while preparing Image download path.");
            }
        }

        static final HttpResponse getResponse(String url, HttpClient client) {
            try {
                HttpGet imageGet = new HttpGet(url);
                return client.execute(imageGet);
            } catch (Throwable e) {
                LOGGER.error("Could get an image response from {}", url, e);
                throw new AssertionError(String.format("Error getting image %s", url));
            }
        }

        HttpClient login(String loginUrl, String user, String credentials) {
            try {
                HttpClient client = new DefaultHttpClient();
                String urlWithParams = String.format(loginUrl, user, credentials);

                HttpGet httpGet = new HttpGet(urlWithParams);
                client.execute(httpGet);
                return client;
            } catch (Throwable e) {
                throw new AssertionError(String.format("Could not login to %s with user=%s", loginUrl, user));
            }
        }
    }

	public List<File> getImages(Iterable<String> imageIds) {
		// TODO Auto-generated method stub
		return null;
	}


}
